﻿namespace MathVisualizer


module Utils =
    open System
    open System.Drawing
    open System.Drawing.Drawing2D 

    let debug p = System.Console.WriteLine("DEBUG: " + p.ToString())


    type mouseEvent = 
        | Click
        | Over

   

    //Contiene informazioni relative ad un evento associato al mouse (mouseEvent)

    
    //Eccezione lanciata in caso la stringa di input non sia ritenuta valida.
    exception InvalidExpression of String


    let measureString (g:Graphics, str, font) : RectangleF =
        let sz1 = g.MeasureString(str, font)
    
        //Define bounding rectangle of _toRender
        let mutable myRectangle1 = new RectangleF(new PointF(0.f, 0.f), sz1)
    
        let chranges = [| new CharacterRange(0, str.Length) |]
    
        let sf = new StringFormat()
        sf.FormatFlags <- StringFormatFlags.NoClip
        sf.SetMeasurableCharacterRanges(chranges)
    
        let mutable sz = new SizeF(0.f, 0.f)
    
        let mutable miny = 0.f
    
    
        if str<>"" then    
            let regions = g.MeasureCharacterRanges(str, font, myRectangle1, sf)
    
            sz <- new SizeF((*regions.[0].GetBounds(arg).Width*) sz1.Width, regions.[0].GetBounds(g).Height)
        sf.Dispose()
    
        // debug("measureString: " + str + "; " + sz.ToString())
        //Il rettangolo che contiene this
        new RectangleF(new PointF(0.f, 0.f), sz)
    
    
    
    let drawPath (g:Graphics) (gp:GraphicsPath) : unit =
        g.DrawPath(Pens.Black, gp)
        g.FillPath(Brushes.Black, gp)
    

    let centerX (baseRect:RectangleF) (toCenter:RectangleF) = baseRect.X + baseRect.Width / 2.f - toCenter.Width / 2.f

    let centerRelX (baseRect:RectangleF) (toCenter:RectangleF) = baseRect.Width / 2.f - toCenter.Width / 2.f

    let centerY (baseRect:RectangleF) (toCenter:RectangleF) = baseRect.Y + baseRect.Height / 2.f - toCenter.Height / 2.f

    let centerRelY (baseRect:RectangleF) (toCenter:RectangleF) = baseRect.Height / 2.f - toCenter.Height / 2.f
    
    let stdfont = new FontFamily("Times New Roman")

    let titlefontfamily = new FontFamily("Verdana")

    let fontsize (level:int, big) = if (big) then 64.f - float32 (2 * level) else 22.f - float32 (8 * level) 
    
    let font(level, big) = new Font(stdfont, fontsize(level, big))

    
    let cdr (node:Expr, parentOffset:PointF) : PointF = new PointF(node.Container.X + parentOffset.X, node.Container.Y + parentOffset.Y)     


    let isGreekLetter (str:string) : bool*string =
            let mutable isgreek = true
            let resstr = match str with
                            | "alpha" ->"\u03b1" | "Alpha" -> "\u0391"
                            | "beta" -> "\u03b2" | "Beta" -> "\u0392"
                            | "gamma" -> "\u03b3" | "Gamma" -> "\u0393"
                            | "delta" -> "\u03b4" | "Delta" -> "\u0394"
                            | "epsilon" -> "\u03b5" | "Epsilon" -> "\u0395"
                            | "zeta" -> "\u03b6" | "Zeta" -> "\u0396"
                            | "eta" -> "\u03b7" | "Eta" -> "\u0397"
                            | "theta" -> "\u03b8" | "Theta" -> "\u0398"
                            | "iota" -> "\u03b9" | "Iota" -> "\u0399"
                            | "kappa" -> "\u03ba" | "Kappa" -> "\u039a"
                            | "lampda" -> "\u03bb" | "Lambda" -> "\u039b"
                            | "mu" -> "\u03bc" | "Mu" -> "\u039c"
                            | "nu" -> "\u03bd" | "Nu" -> "\u039d"
                            | "xi" -> "\u03be" | "Xi" -> "\u039e"
                            | "omicron" -> "\u03bf" | "Omicron" -> "\u039f"
                            | "pi" -> "\u03c0" | "Pi" -> "\u03a0"
                            | "rho" -> "\u03c1" | "Rho" -> "\u03a1"
                            | "sigma" -> "\u03c3" | "Sigma" -> "\u03a3"
                            | "tau" -> "\u03c4" | "Tau" -> "\u03a4"
                            | "upsilon" -> "\u03c5" | "Upsilon" -> "\u03a5"
                            | "phi" -> "\u03c6" | "Phi" -> "\u03a6"
                            | "chi" -> "\u03c7" | "Chi" -> "\u03a7"
                            | "psi" -> "\u03c8" | "Psi" -> "\u03a8"
                            | "omega" -> "\u03c9" | "Omega" -> "\u03a9"
                            | "infty" -> "\u221e"
                            | _ -> isgreek<-false; str
            isgreek, resstr

   

    let rec visitTree (e:Expr) = 
        match e.Expr with
            |BigSum(p1, p2, arg) -> debug("BigSum: " + e.Box.ToString()); visitTree(p1); visitTree(p2); visitTree(arg)

            |Literal(p1) -> debug("Literal: " + p1 + "; " + e.Box.ToString()); 
            | _ -> ()
        ()


 

    let toPointF (p:Point) = PointF(float32 p.X, float32 p.Y)
